home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK2.toast / Development Kits (Disc 2) / QuickDraw GX / Programming Stuff / GXEdit Library & Doc / GXEditFileIO.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-10  |  16.7 KB  |  751 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:                GXEditFileIO.c
  3.     
  4.     Contains:
  5.     
  6.     Written by:        Barton R. House
  7.     
  8.     Copyright:        © 1993 by Apple Computer, Inc., All rights reserved.
  9.     
  10. */
  11.  
  12. #include "GXEdit.h"
  13. #include "GXEditDoc.h"
  14. #include "GXEditDebug.h"
  15. #include "GXEditError.h"
  16. #include "GXEditUtils.h"
  17. #include "GXEditSelection.h"
  18. #include "GXEditValidation.h"
  19. #include "GXEditStyle.h"
  20.  
  21. /* GX includes */
  22.  
  23. #include "graphics toolbox.h"
  24. #include "graphics routines.h"
  25. #include "math routines.h"
  26.  
  27. #define kBufferSize        2056
  28.  
  29. static void WriteParagraph(short fRefNum, ParaPtr pp);
  30. static void WriteLine(short fRefNum, LinePtr lp);
  31. static void WriteNewRun(short fRefNum, NewRunPtr rp);
  32. static void WriteStyle(DocPtr dp, short fRefNum, StylePtr sp);
  33. static void WriteData(short fRefNum, Ptr p, long size);
  34. static void WriteLong(short fRefNum, long l);
  35. static void WriteShort(short fRefNum, short s);
  36. static void WriteBoolean(short fRefNum, Boolean b);
  37.  
  38.  
  39. static void ReadParagraph(DocPtr dp, short fRefNum, ParaPtr pp);
  40. static void ReadLine(short fRefNum, LinePtr lp);
  41. static void ReadNewRun(DocPtr dp, short fRefNum, NewRunPtr rp);
  42. static void ReadStyle(DocPtr dp, short fRefNum, StylePtr sp);
  43. static void ReadLayout(DocPtr dp, short fRefNum, gxShape * layoutPtr);
  44. static void ReadData(short fRefNum, Ptr p, long size);
  45. static void ReadLong(short fRefNum, long * l);
  46. static void ReadShort(short fRefNum, short * s);
  47. static void ReadBoolean(short fRefNum, Boolean * b);
  48.  
  49. boolean gGXEditForceReflowOnOpenDoc = false;
  50.  
  51. /* FILE FORMAT - Version 1
  52.  
  53.     magic                                long
  54.     version                                long
  55.     
  56.     doc
  57.     
  58.         length                            long
  59.         numStyles                            short
  60.         numText                            long
  61.         numParagraphs                        short
  62.         top                                long
  63.         vertical                            Boolean        (added in version 1)
  64.         
  65.     selection
  66.     
  67.         startDocOffset                        long
  68.         endDocOffset                        long
  69.         endOfLine                            Boolean
  70.     
  71.     styles[numStyles]
  72.     
  73.         styleSize                            long
  74.         
  75.         flatten data                        char[styleSize]
  76.         
  77.     paragraphs[numPara]
  78.     
  79.         start                                short
  80.         width                            short
  81.         height                            short
  82.         docOffset                            long
  83.         numText                            short
  84.         numLines                            short
  85.         numRuns                            short
  86.         options                            gxLayoutOptions        (this should be a private data structure)
  87.         
  88.         lines[numLines]
  89.         
  90.             start                            short
  91.             paraOffset                    short
  92.             numText                        short
  93.         
  94.         runs[numRuns]
  95.         
  96.             styleIndex                        short
  97.             paraOffset                    short
  98.             numText                        short
  99.             textSize                        short
  100.             
  101.             text                            char[numText * textSize]
  102.         
  103. */
  104.  
  105. typedef struct {
  106.     gxSpoolBlock        sb;            /* this must be first */
  107.     short            fRefNum;
  108.     long            start;
  109.     long            numBytes;
  110.     DocPtr            dp;
  111. } MySpoolBlock;
  112.  
  113. static long MySpoolProcedure(gxSpoolCommand command, gxSpoolBlock * sb);
  114.  
  115. void DocSave(DocPtr dp, short fRefNum)
  116. {
  117.     ParaPtr            pp;
  118.     StylePtr        sp;
  119.     short            paragraphIndex;
  120.     short            styleIndex;
  121.     
  122.     /* write out magic */
  123.     
  124.     WriteLong(fRefNum, kGXEditMagic);
  125.     
  126.     /* write out file format version */
  127.     
  128.     WriteLong(fRefNum, kGXEditFileVersion);
  129.     
  130.     /* write out the document information */
  131.     
  132.     WriteLong(fRefNum, dp->length);
  133.     WriteShort(fRefNum, dp->numStyles);
  134.     WriteLong(fRefNum, dp->numText);
  135.     WriteShort(fRefNum, dp->numParagraphs);
  136.     WriteLong(fRefNum, dp->top);
  137.     WriteBoolean(fRefNum, dp->verticalText);
  138.     
  139.     /* write out selection information */
  140.     
  141.     WriteLong(fRefNum, dp->selection.startDocOffset);
  142.     WriteLong(fRefNum, dp->selection.endDocOffset);
  143.     WriteBoolean(fRefNum, dp->selection.endOfLine);
  144.     
  145.     /* write out gxStyle information */
  146.     
  147.     HLock((Handle) dp->styles);
  148.     
  149.     for(sp = *dp->styles, styleIndex = 0; styleIndex < dp->numStyles; styleIndex++, sp++)
  150.         WriteStyle(dp, fRefNum, sp);
  151.         
  152.     HUnlock((Handle) dp->styles);
  153.     
  154.     /* write out the paragraphs */
  155.     
  156.     HLock((Handle) dp->paragraphs);
  157.     
  158.     for(paragraphIndex=0, pp = *dp->paragraphs; paragraphIndex < dp->numParagraphs; paragraphIndex++,pp++)
  159.         WriteParagraph(fRefNum, pp);
  160.     
  161.     HUnlock((Handle) dp->paragraphs);
  162.         
  163. }
  164.  
  165. static void WriteParagraph(short fRefNum, ParaPtr pp)
  166. {
  167.     LinePtr            lp;
  168.     short            lineIndex;
  169.     NewRunPtr        rp;
  170.     short            runIndex;
  171.     
  172.     WriteShort(fRefNum, pp->start);
  173.     WriteShort(fRefNum, pp->width);
  174.     WriteShort(fRefNum, pp->height);
  175.     WriteLong(fRefNum, pp->docOffset);
  176.     WriteShort(fRefNum, pp->numText);
  177.     WriteShort(fRefNum, pp->numLines);
  178.     WriteShort(fRefNum, pp->numRuns);
  179.     
  180.     /* this should really use a private structure */
  181.     
  182.     WriteData(fRefNum, (Ptr) &pp->layoutOptions, sizeof(pp->layoutOptions));
  183.     
  184.     /* write out lines */
  185.         
  186.     HLock((Handle) pp->lines);
  187.     
  188.     for(lineIndex=0, lp = *pp->lines; lineIndex < pp->numLines; lineIndex++, lp++)
  189.         WriteLine(fRefNum, lp);
  190.     
  191.     HUnlock((Handle) pp->lines);
  192.     
  193.     /* write out runs */
  194.     
  195.     HLock((Handle) pp->runs);
  196.     
  197.     for(runIndex = 0, rp = *pp->runs; runIndex < pp->numRuns; runIndex++, rp++)
  198.         WriteNewRun(fRefNum, rp);
  199.         
  200.     HUnlock((Handle) pp->runs);
  201.     
  202. }
  203.  
  204. static void WriteLine(short fRefNum, LinePtr lp)
  205. {
  206.     WriteShort(fRefNum, lp->start);
  207.     WriteShort(fRefNum, lp->paraOffset);
  208.     WriteShort(fRefNum, lp->numText);    
  209.         
  210. }
  211.  
  212. static void WriteNewRun(short fRefNum, NewRunPtr rp)
  213. {
  214.     WriteShort(fRefNum, rp->styleIndex);
  215.     WriteShort(fRefNum, rp->paraOffset);
  216.     WriteShort(fRefNum, rp->numText);
  217.     WriteShort(fRefNum, 0);                        /* WriteShort(fRefNum, rp->textSize); */
  218.     
  219.     /* save out text */
  220.     
  221.     HLock((Handle) rp->text);
  222.     
  223.     WriteData(fRefNum, *rp->text, rp->numText);
  224.         
  225.     HUnlock((Handle) rp->text);
  226.     
  227. }
  228.  
  229. static void WriteStyle(DocPtr dp, short fRefNum, StylePtr sp)
  230. {
  231.     MySpoolBlock        msb;
  232.     gxShape                emptyShape;
  233.     long                startOfStyle;
  234.     long                endOfStyle;
  235.     long                styleSize;
  236.     OSErr                err;
  237.     
  238.     /* save the file position of start of gxStyle */
  239.     
  240.     GetFPos(fRefNum, &startOfStyle);
  241.     
  242.     /* save out the size of the flatten gxStyle */
  243.     
  244.     styleSize = 0;    /* we don't know how big the flatten gxStyle is yet */
  245.     
  246.     WriteLong(fRefNum, styleSize);
  247.  
  248.     /* save out the flatten gxStyle information */
  249.     
  250.     msb.sb.buffer = NewPtr(kBufferSize);
  251.     msb.sb.bufferSize = kBufferSize;
  252.     msb.sb.spoolProcedure = MySpoolProcedure;
  253.     
  254.     GetFPos(fRefNum, &msb.start);
  255.     
  256.     msb.fRefNum = fRefNum;
  257.     msb.numBytes = 0;
  258.     msb.dp = dp;
  259.     
  260.     /* create an empty gxShape and set the gxStyle to the gxStyle we want to save */
  261.     
  262.     emptyShape = GXNewShape(gxEmptyType);
  263.     GXSetShapeStyle(emptyShape, sp->textStyle);
  264.     
  265.     /* look into setting the flags so that a list of fonts that are used is generated */
  266.     
  267.     GXFlattenShape(emptyShape, (gxFlattenFlag) 0, (gxSpoolBlock *) &msb);
  268.     
  269.     /* dispose of the temporary gxShape */
  270.     
  271.     GXDisposeShape(emptyShape);
  272.  
  273.     /* now record the file position for the end of the gxStyle */
  274.     
  275.     GetFPos(fRefNum, &endOfStyle);
  276.     
  277.     /* double check the file position with the number of bytes written */
  278.     
  279.     if(msb.numBytes + msb.start != endOfStyle)
  280.         gxEditPostError(dp, gx_edit_internal_fatal_error);
  281.         
  282.     /* finish up recording the size of the flatten gxStyle */
  283.     
  284.     styleSize = endOfStyle - msb.start;
  285.     
  286.     if((err = SetFPos(fRefNum, fsFromStart, startOfStyle)) != noErr)
  287.         gxEditPostError(dp, gx_edit_internal_fatal_error);
  288.  
  289.     WriteLong(fRefNum, styleSize);
  290.             
  291.     if((err = SetFPos(fRefNum, fsFromStart, endOfStyle)) != noErr)
  292.         gxEditPostError(dp, gx_edit_internal_fatal_error);
  293.     
  294.     /* free up the buffer */
  295.     
  296.     DisposePtr(msb.sb.buffer);
  297.     
  298. }
  299.  
  300.  
  301. static void WriteData(short fRefNum, Ptr p, long size)
  302. {
  303.     long        count;
  304.     OSErr        err;
  305.     
  306.     count = size;
  307.         
  308.     if((err = FSWrite(fRefNum, &count, p)) != noErr)
  309.         gxEditPostError(nil, gx_edit_internal_fatal_error);
  310.         
  311.     if(count != size)
  312.         gxEditPostError(nil, gx_edit_internal_fatal_error);
  313.         
  314. }
  315.  
  316. static void WriteLong(short fRefNum, long l)
  317. {
  318.     WriteData(fRefNum, (Ptr) &l, sizeof(long));
  319. }
  320.  
  321. static void WriteShort(short fRefNum, short s)
  322. {
  323.     WriteData(fRefNum, (Ptr) &s, sizeof(short));
  324. }
  325.  
  326. static void WriteBoolean(short fRefNum, Boolean b)
  327. {
  328.     WriteData(fRefNum, (Ptr) &b, sizeof(Boolean));
  329. }
  330.         
  331. void DocOpen(DocHan * docHanPtr, Rect * viewRect, gxViewPort docViewPort, short fRefNum, short leftMargin, short rightMargin)
  332. {
  333.     DocHan                doc;
  334.     DocPtr                dp;
  335.     ParaPtr                pp;
  336.     StylePtr            sp;
  337.     short                paraIndex;
  338.     short                styleIndex;
  339.     gxViewPort            newViewPort;
  340.     gxShape                clip;
  341.     gxRectangle            rect;
  342.     long                magic;
  343.     long                version;
  344.     
  345.     doc = (DocHan) NewHandle(sizeof(DocRec));
  346.     
  347.     HLock((Handle) doc);
  348.     
  349.     dp = *doc;
  350.     
  351.     /* read in magic */
  352.     
  353.     ReadLong(fRefNum, &magic);
  354.     
  355.     if(magic != kGXEditMagic)
  356.         gxEditPostError(nil, gx_edit_internal_fatal_error);
  357.  
  358.     /* read the file format version */
  359.     
  360.     ReadLong(fRefNum, &version);
  361.     
  362.     if(version != kGXEditFileVersion && version != kGXEditFileVersion0)
  363.         gxEditPostError(nil, gx_edit_internal_fatal_error);
  364.  
  365.     /* read the the document information */
  366.     
  367.     ReadLong(fRefNum, &dp->length);
  368.     ReadShort(fRefNum, &dp->numStyles);
  369.     ReadLong(fRefNum, &dp->numText);
  370.     ReadShort(fRefNum, &dp->numParagraphs);
  371.     ReadLong(fRefNum, &dp->top);
  372.     if(version != kGXEditFileVersion0)
  373.         ReadBoolean(fRefNum, &dp->verticalText);
  374.     else
  375.         dp->verticalText = false;
  376.         
  377.     /* read the selection information */
  378.     
  379.     ReadLong(fRefNum, &dp->selection.startDocOffset);
  380.     ReadLong(fRefNum, &dp->selection.endDocOffset);
  381.     ReadBoolean(fRefNum, &dp->selection.endOfLine);
  382.             
  383.     /* set generic doc information */
  384.     
  385.     dp->magic = magic;
  386.     dp->active = false;
  387.     
  388.     /* set the error control values */
  389.     
  390.     dp->errorProc = nil;
  391.     dp->error = 0;
  392.     dp->stickyError = 0;
  393.     
  394.     /* set the correct view port and view rect */
  395.     
  396.     dp->lineWidth = viewRect->right - viewRect->left - leftMargin - rightMargin;
  397.     dp->leftMargin = leftMargin;
  398.     dp->rightMargin = rightMargin;
  399.     
  400.     if(dp->verticalText)
  401.         dp->viewHeight = viewRect->right - viewRect->left;
  402.     else
  403.         dp->viewHeight = viewRect->bottom - viewRect->top;
  404.     
  405.     dp->viewRect = *viewRect;
  406.     
  407.     newViewPort = GXCopyToViewPort(nil, docViewPort);
  408.     GXSetViewPortParent(newViewPort, docViewPort);
  409.     rect.top = ff(viewRect->top);
  410.     rect.left = ff(viewRect->left);
  411.     rect.right = ff(viewRect->right);
  412.     rect.bottom = ff(viewRect->bottom);
  413.     clip = GXNewRectangle(&rect);
  414.  
  415.     /* This ignores is needed because we do not keep track of the current
  416.           clip of the view port.  Thus, we will often set the clip to the same rect
  417.           which generates a notice*/
  418.  
  419. #ifdef debugging
  420.     GXIgnoreGraphicsNotice(clip_already_set);
  421. #endif
  422.  
  423.     GXSetViewPortClip(newViewPort, clip);
  424.     
  425. #ifdef debugging
  426.     GXPopGraphicsNotice();
  427. #endif
  428.     
  429.     GXDisposeShape(clip);
  430.     
  431.     dp->docViewPort = newViewPort;
  432.     
  433.     /* allocate offscreen gxBitmap and viewport */
  434.     
  435.     dp->offscreenBytes = nil;
  436.     dp->offscreenPort = nil;
  437.     dp->offscreenDevice = nil;
  438.     dp->offscreenGroup = nil;
  439.     dp->offscreenBitmap = nil;
  440.         
  441.     gxEditBuildOffscreen(dp);
  442.     
  443.     /* read in the styles */
  444.     
  445.     dp->styles = (StyleHan) NewHandle(sizeof(StyleRec) * dp->numStyles);
  446.     
  447.     HLock((Handle) dp->styles);
  448.     
  449.     for(styleIndex=0, sp = *dp->styles; styleIndex<dp->numStyles; styleIndex++, sp++)
  450.         ReadStyle(dp, fRefNum, sp);
  451.     
  452.     HUnlock((Handle) dp->styles);
  453.     
  454.     /* read in the paragraphs */
  455.     
  456.     dp->paragraphs = (ParaHan) NewHandle(sizeof(ParaRec) * dp->numParagraphs);
  457.     
  458.     HLock((Handle) dp->paragraphs);
  459.     
  460.     for(paraIndex=0, pp = *dp->paragraphs; paraIndex<dp->numParagraphs; paraIndex++, pp++)
  461.         ReadParagraph(dp, fRefNum, pp);
  462.     
  463.     HUnlock((Handle) dp->paragraphs);
  464.         
  465.     /* initialize empty scrap */
  466.     
  467.     dp->scrap.numText = 0;
  468.     dp->scrap.numRuns = 0;
  469.     dp->scrap.runs = (NewRunHan) NewHandle(0);
  470.     
  471.     /* invalidate the entire document for drawing purposes */
  472.     
  473.     dp->drawn = false;
  474.     
  475.     /* set the paragraph widths and reflow if the paragraph width has changed  */
  476.     
  477.     pp = *dp->paragraphs;
  478.     
  479.     for(paraIndex = 0; paraIndex < dp->numParagraphs; paraIndex++, pp++)
  480.         if(pp->width != dp->lineWidth || gGXEditForceReflowOnOpenDoc) {
  481.             
  482.             pp->width = dp->lineWidth;
  483.             pp->layoutOptions.width = ff(pp->width);
  484.             
  485.             if(pp->numLines) {
  486.             
  487.                 pp->reflow = true;
  488.                 (*pp->lines)[0].reflow = true;
  489.                 
  490.             }
  491.             
  492.         }
  493.         
  494.     /* setup the current selection */
  495.     
  496.     dp->numCurrentFonts = 0;
  497.     dp->currentFonts = (gxFont **) NewHandle(0);
  498.     
  499.     dp->numCurrentStyles = 0;
  500.     dp->currentStyles = (short **) NewHandle(0);
  501.     
  502.     dp->currentSize = 0;
  503.     dp->emptyStyle = 0;
  504.     
  505.     SetSelection(dp, dp->selection.startDocOffset, dp->selection.endDocOffset, true, dp->selection.endOfLine, true); 
  506.     
  507.     DocSetMaxTop(dp);
  508.     
  509.     ValidateDoc(dp);
  510.  
  511.     if (gGXEditForceReflowOnOpenDoc)
  512.         while (DocReflow(dp))
  513.             ;
  514.  
  515.     HUnlock((Handle) doc);
  516.     
  517.     *docHanPtr = doc;
  518. }
  519.  
  520. static void ReadParagraph(DocPtr dp, short fRefNum, ParaPtr pp)
  521. {
  522.     LinePtr                lp;
  523.     short                lineIndex;
  524.     NewRunPtr            rp;
  525.     short                runIndex;
  526.     
  527.     ReadShort(fRefNum, &pp->start);
  528.     ReadShort(fRefNum, &pp->width);
  529.     ReadShort(fRefNum, &pp->height);
  530.     ReadLong(fRefNum, &pp->docOffset);
  531.     ReadShort(fRefNum, &pp->numText);
  532.     ReadShort(fRefNum, &pp->numLines);
  533.     ReadShort(fRefNum, &pp->numRuns);
  534.     
  535.     pp->drawn = false;
  536.     pp->reflow = false;
  537.     pp->dirty = false;    /* the line heights and starts are still good */
  538.     
  539.     /* this should really use a private structure */
  540.     
  541.     ReadData(fRefNum, (Ptr) &pp->layoutOptions, sizeof(pp->layoutOptions));
  542.     
  543.     /* adjust the layout options */
  544.     
  545.     pp->layoutOptions.baselineRec = nil;        /* FUTURE ENHANCEMENT -- THIS SHOULD BE RESTORED */
  546.     
  547.     /* read in the lines */
  548.     
  549.     pp->lines = (LineHan) NewHandle(pp->numLines * sizeof(LineRec));
  550.     
  551.     HLock((Handle) pp->lines);
  552.     
  553.     for(lineIndex = 0, lp = *pp->lines; lineIndex < pp->numLines; lineIndex++, lp++)
  554.         ReadLine(fRefNum, lp);
  555.         
  556.     HUnlock((Handle) pp->lines);
  557.     
  558.     /* read in runs */
  559.     
  560.     pp->runs = (NewRunHan) NewHandle(pp->numRuns * sizeof(NewRunRec));
  561.     
  562.     HLock((Handle) pp->runs);
  563.     
  564.     for(runIndex = 0, rp = *pp->runs; runIndex < pp->numRuns; runIndex++, rp++)
  565.         ReadNewRun(dp, fRefNum, rp);
  566.         
  567.     HUnlock((Handle) pp->runs);
  568.     
  569. }
  570.  
  571.  
  572. static void ReadLine(short fRefNum, LinePtr lp)
  573. {
  574.     #pragma unused(dp)
  575.  
  576.     ReadShort(fRefNum, &lp->start);
  577.     ReadShort(fRefNum, &lp->paraOffset);
  578.     ReadShort(fRefNum, &lp->numText);
  579.     
  580.     lp->layout = nil;
  581.     lp->layoutPos.x = 0; lp->layoutPos.y = 0;
  582.     lp->dirty = true;
  583.     lp->reflow = false;
  584.     lp->drawn = false;
  585.     lp->selected = false;
  586.     
  587.     lp->ascent = 0;
  588.     lp->descent = 0;
  589.     
  590. }
  591.  
  592. static void ReadNewRun(DocPtr dp, short fRefNum, NewRunPtr rp)
  593. {
  594.     short            dummy;
  595.     
  596.     ReadShort(fRefNum, &rp->styleIndex);
  597.     
  598.     IncrementDocStyleRefCount(dp, rp->styleIndex);
  599.     
  600.     ReadShort(fRefNum, &rp->paraOffset);
  601.     ReadShort(fRefNum, &rp->numText);
  602.     ReadShort(fRefNum, &dummy);                /*    ReadShort(fRefNum, &rp->textSize);    */
  603.                                         
  604.     /* read in text */
  605.     
  606.     rp->text = (void **) NewHandle(rp->numText);
  607.  
  608.     HLock((Handle) rp->text);
  609.     
  610.     ReadData(fRefNum, *rp->text, rp->numText);
  611.         
  612.     HUnlock((Handle) rp->text);
  613.         
  614. }
  615.  
  616. static void ReadStyle(DocPtr dp, short fRefNum, StylePtr sp)
  617. {
  618.     MySpoolBlock        msb;
  619.     gxShape                emptyShape;
  620.     long                styleSize;
  621.     
  622.     ReadLong(fRefNum, &styleSize);
  623.  
  624.     /* readin the GX gxStyle information */
  625.     
  626.     msb.sb.buffer = NewPtr(kBufferSize);
  627.     msb.sb.bufferSize = kBufferSize;
  628.     msb.sb.spoolProcedure = MySpoolProcedure;
  629.     
  630.     GetFPos(fRefNum, &msb.start);
  631.     
  632.     msb.numBytes = styleSize;
  633.     
  634.     msb.fRefNum = fRefNum;
  635.     msb.dp = dp;
  636.     
  637.     emptyShape = GXUnflattenShape((gxSpoolBlock *) &msb, 1, &dp->docViewPort );
  638.     
  639.     sp->textStyle = GXGetShapeStyle(emptyShape);        /* this does not increment the owner count */
  640.     sp->textStyle = GXCopyToStyle(nil, sp->textStyle);
  641.     
  642.     GXDisposeShape(emptyShape);
  643.     
  644.     /* check that the correct number of bytes was read */
  645.     
  646.     if(msb.numBytes != 0)
  647.         gxEditPostError(dp, gx_edit_internal_fatal_error);
  648.     
  649.     DisposePtr(msb.sb.buffer);
  650.     
  651.     /* initialize the redundant data */
  652.     
  653.     sp->textFont = GXGetStyleFont(sp->textStyle);
  654.     sp->textSize = FixedToInt(GXGetStyleTextSize(sp->textStyle));
  655.     sp->platform = GXGetStyleEncoding(sp->textStyle, &sp->script, &sp->language);
  656.     
  657.     /* initial zero value for refCount */
  658.     
  659.     sp->refCount = 0;
  660. }
  661.  
  662. static void ReadData(short fRefNum, Ptr p, long size)
  663. {
  664.     long                count;
  665.     OSErr                err;
  666.     
  667.     count = size;
  668.     
  669.     if((err = FSRead(fRefNum, &count, p)) != noErr)
  670.         gxEditPostError(nil, gx_edit_internal_fatal_error);
  671.         
  672.     if(count != size)
  673.         gxEditPostError(nil, gx_edit_internal_fatal_error);
  674.         
  675. }
  676.  
  677. static void ReadLong(short fRefNum, long * l)
  678. {
  679.     ReadData(fRefNum, (Ptr) l, sizeof(long));
  680. }
  681.  
  682. static void ReadShort(short fRefNum, short * s)
  683. {
  684.     ReadData(fRefNum, (Ptr) s, sizeof(short));
  685. }
  686.  
  687. static void ReadBoolean(short fRefNum, Boolean * b)
  688. {
  689.     ReadData(fRefNum, (Ptr) b, sizeof(Boolean));
  690. }
  691.         
  692. static long MySpoolProcedure(gxSpoolCommand command, gxSpoolBlock * sb)
  693. {
  694.     long                count;
  695.     MySpoolBlock        * msb;
  696.     OSErr                err;
  697.     
  698.     msb = (MySpoolBlock *) sb;
  699.     
  700.     switch(command) {
  701.     
  702.     case gxOpenReadSpool:
  703.     case gxOpenWriteSpool:
  704.     
  705.         SetFPos(msb->fRefNum, fsFromStart, msb->start);
  706.         break;
  707.         
  708.     case gxReadSpool:
  709.     
  710.         count = sb->count;
  711.         
  712.         if(count > msb->numBytes) {
  713.         
  714.             count = msb->numBytes;
  715.             sb->bufferSize = msb->numBytes;
  716.             
  717.         }
  718.         
  719.         if((err = FSRead(msb->fRefNum, &count, sb->buffer)) != noErr)
  720.             gxEditPostError(msb->dp, gx_edit_internal_fatal_error);
  721.         
  722.         if((sb->count > msb->numBytes && count != msb->numBytes) ||
  723.             (sb->count <= msb->numBytes && count != sb->count))
  724.             gxEditPostError(msb->dp, gx_edit_internal_fatal_error);
  725.         
  726.         msb->numBytes -= count;
  727.         
  728.         break;
  729.         
  730.     case gxWriteSpool:
  731.  
  732.         count = sb->count;
  733.         
  734.         if((err = FSWrite(msb->fRefNum, &count, sb->buffer)) != noErr)
  735.             gxEditPostError(msb->dp, gx_edit_internal_fatal_error);
  736.  
  737.         if(sb->count != count)
  738.             gxEditPostError(msb->dp, gx_edit_internal_fatal_error);
  739.         
  740.         msb->numBytes += count;
  741.         
  742.         break;
  743.         
  744.     case gxCloseSpool:
  745.         break;
  746.     }
  747.     
  748.     return(noErr);
  749.     
  750. }
  751.